<template>
	<div class="content">
		<div class="j-header">
			<span @click="arrowSet(1)" class="iconfont icon-youjiantou" title="箭头"></span>
			<span @click="arrowSet(0)" class="iconfont icon-wujiantou" title="无箭头"></span>
			<span @click="lineSet('Straight')" class="iconfont icon-zhixian" title="直线"></span>
			<span @click="lineSet('Flowchart')" class="iconfont icon-zhexian" title="折线"></span>
			<span @click="lineSet('Bezier')" class="iconfont icon-qvxian" title="曲线"></span>
			<span @click="save" class="iconfont icon-baocun">保存</span>
		</div>
		
			<div :class="panelclass">
				<!-- 左侧操作 -->
				<slot name="operate">
					<div class="flex">
						<div class="flex-child" @dragstart="dragstart($event,'节点','type1')" draggable="true" @dragend="imgEnd">
							<span class="type1">常规节点</span>
						</div>
						<div class="flex-child" @dragstart="dragstart($event,'节点','type2')" draggable="true" @dragend="imgEnd"><span
							 class="type2">常规节点</span></div>
						<div class="flex-child" @dragstart="dragstart($event,'节点','type3')" draggable="true" @dragend="imgEnd"><span
							 class="type3">常规节点</span></div>
						<div class="flex-child" @dragstart="dragstart($event,'节点','type4')" draggable="true" @dragend="imgEnd"><span
							 class="type4">常规节点</span></div>
					</div>
				</slot>
			</div>
			<div class="j-container"  :style="{width:width+'px',height:height+'px'}">
			<!-- 鹰眼图 -->
			<div
				@mousedown.stop="eyesMouseDown"
				@mousemove.stop="eyesMouseMove"
				@mouseup.stop="eyesMouseUp"
			 class="little-map">
			 <div :style="{left:eyesdynamicPx.x+'px',top:eyesdynamicPx.y+'px'}" class="mask"></div>
				<div class="littie-div"
					v-for="(item,index) in eyesData"
					:style="{left:(item.x- Math.abs(middlePx.x))/10+'px',top:(item.y- Math.abs(middlePx.y))/6+'px'}">
				</div>
			</div>
			<!-- 画布 -->
			<div id="nodeCanvas" 
			 @drop.prevent="drop"
			 @dragover.prevent 
			 @click="sceneClick"
			 @mousedown="nodeMouseDown"
			 @mousemove="nodeMouseMove"
			 @mouseup="nodeMouseUp"
			 
			 >
			 
			 <div class="group-container" id="container1" group="groupone">
				 
			 
				<slot :data="nodeData">
					<div class="j-node" v-for="(item,index) in nodeData" :id="nodeId+item.id" :style="{left:item.x+'px',top:item.y+'px'}"
					 @mouseenter="nodeEnter(index)" @mouseleave="nodeLeave" @click.stop="nodeClick(index)" :class="[clickIndex == index?'active-'+item.type:'',item.type]">
						{{item.name}}
						<span v-show="selectIndex==index" style="margin-right: 10px;" class="del" @click="nodeRemove(item.id)">X</span>
					</div>
				</slot>
				</div>
			</div>
			</div>
			
			<!-- 右侧数据 -->
			<div :class="dataclass">
				<h3 class="d-title" v-show="sceneState=='scene'">画布</h3>
				<h3 class="d-title" v-show="sceneState=='node'">节点</h3>
				<slot :selectData="selectData" name="selectData">
					<form v-show="sceneState=='node'" class="d-form">
						<div class="d-p">
							<label for="">节点名称</label>
							<input type="text" v-model="selectData.name">
						</div>
						<div class="d-p">
							<label for="">节点类型</label>
							<input type="text" v-model="selectData.type">
						</div>
					</form>
				</slot>
			</div>
		

	</div>
</template>

<script>
	import {
		jsPlumb
	} from "jsplumb"
	import visoConfig from "./config.js"
	export default {
		name: 'nodeCanvas',
		data() {
			return {
				jspNode: null,
				nodeData: [],
				eyesData:[],
				nodeIndex: 0,
				selectIndex: -1,
				clickIndex: -1,
				selectData: {},
				active: 'active',
				connectArry: [],
				visoConfig: null,
				offsetX: '',
				offsetY: '',
				canvasX: 200,
				canvasY: 0,
				canvasOffsetX:'',
				canvasOffsetY:'',
				eyescanvasOffsetX:'',
				eyescanvasOffsetY:'',
				sceneState: 'scene',//当前点击对象是画布还是节点
				mouseState:false,//控制是否拖动画布
				eyesState:false,//控制鹰眼图拖动
				initPx:{x:-200,y:-200},//初始位置
				dynamicPx:{x:-200,y:-200},
				eyesdynamicPx:{},//鹰眼图的初始位置
				middlePx:{}
			}
		},
		props: {
			width: {
				type: Number,
				default: 1000
			},
			height: {
				type: Number,
				default: 600
			},
			panelclass: {
				type: String,
				default: 'j-panel'
			},
			dataclass: {
				type: String,
				default: 'j-data'
			},
			nodeId: {
				type: String,
				default: 'jNode'
			}

		},
		computed:{
			 magnificationX:function(){
				 return (3000-this.width)/(100+100)
			 },
			magnificationY:function(){
				return (3000-this.height)/(100+100)
			}
		},
		mounted() {
			this.initNode();
			this.setWidth()
			this.visoConfig = visoConfig.visoConfig
		},
		methods: {
			setWidth(){
				let x =0-(3000 - this.width)/2;
				let y =0-(3000 - this.height)/2;
				let obj = {
					x,y
				}
				this.initPx = Object.assign({},obj);
				this.dynamicPx = Object.assign({},obj)
			},
			initNode() {
				var that = this;
				jsPlumb.ready(function() {
					var instance = window.jsp = jsPlumb.getInstance({

						Container: "nodeCanvas"
					});
					//   删除链接连
					instance.bind('click', (conn) => {
						let conc = conn.endpoints[0].elementId + '_' + conn.endpoints[1].elementId
						if (confirm("确定删除连线?")) {
							for (let i = 0; i < that.connectArry.length; i++) {
								if (conc == that.connectArry[i]) {
									that.connectArry.splice(i, 1)
								}
							}
							instance.deleteConnection(conn)
						}
					})
					// 两个节点不能连两次
					instance.bind('beforeDrop', (info) => {
						let lastCoon = info.sourceId + '_' + info.targetId;
						let sign;
						if (that.connectArry.length > 0) {
							for (let c of that.connectArry) {
								console.log(c + ',,,' + lastCoon)
								if (c == lastCoon) {
									sign = 0
									break
								} else {
									sign = 1
									break
								}
							}
						} else {
							sign = 1
						}
						if (sign) {
							that.connectArry.push(lastCoon)
							return true;
						} else {
							return false;
						}
					})

					
					that.jspNode = instance
				})
			},
			// 拖拽
			dragstart(ev, name, type) {
				let o = {
					name: name + this.nodeIndex,
					type: type,
					id: this.nodeIndex,
					isDrop: true
				}
				console.log(ev);
				ev.dataTransfer.setData('Text', JSON.stringify(o))
				this.offsetX = ev.offsetX
				this.offsetY = ev.offsetY
			},
			drop(e) {
				const that = this;
				let info = JSON.parse(e.dataTransfer.getData('Text'))
				console.log(e);
				if (info.isDrop) {
					info.x = e.offsetX-35
					info.y =e.offsetY-35
					this.nodeIndex += 1
					this.nodeData.push(info)
					setTimeout(function() {
						that.addEndpoint(info.id)
						that.middlePx = Object.assign({},that.dynamicPx) ;
						that.eyesData = that.getEyesData(that.dynamicPx)
					}, 300)
				}
			},
			imgEnd(event) {
				console.log('done')
				console.log(event)
				event.dataTransfer.clearData()
			},
			// 添加节点
			addNode(name, type) {
				const that = this;
				let o = {
					name: name + this.nodeIndex,
					type: type,
					id: this.nodeIndex
				}
				this.nodeIndex += 1
				this.nodeData.push(o)

				setTimeout(function() {
					that.addEndpoint(o.id)
				}, 300)

			},
			//添加连接点
			addEndpoint(id) {
				this.jspNode.addEndpoint(this.nodeId + id,this.visoConfig),
// 				this.jspNode.addEndpoint(this.nodeId + id, {
// 						anchors: "TopCenter"
// 					}, this.visoConfig),
// 					this.jspNode.addEndpoint(this.nodeId + id, {
// 						anchors: "RightMiddle"
// 					}, this.visoConfig),
// 					this.jspNode.addEndpoint(this.nodeId + id, {
// 						anchors: "BottomCenter"
// 					}, this.visoConfig),
// 					this.jspNode.addEndpoint(this.nodeId + id, {
// 						anchors: "LeftMiddle"
// 					}, this.visoConfig)
				this.jspNode.draggable(jsPlumb.getSelector("#" + this.nodeId + id))
			},
			//hover事件
			nodeEnter(index) {
				this.selectIndex = index
			},
			nodeLeave() {
				this.selectIndex = -1
			},
			// 节点点击事件
			nodeClick(index) {
				this.sceneState = "node"
				this.clickIndex = index
				this.selectData = this.nodeData[index]
			},
			// 画布点击事件
			sceneClick() {
				this.sceneState = "scene"
				this.clickIndex = -1
			},
			// 画布移动
			nodeMouseDown(e) {
				this.mouseState = true
				this.canvasOffsetX=e.clientX-e.target.offsetLeft;
				this.canvasOffsetY=e.clientY-e.target.offsetTop;
			},
			/*
			左侧大正方形 3000*3000，小正方行 1000*600;左右移动距离3000-1000；上下移动距离3000-600
			右侧小正方形 200*120，外层矩形 300*100；左右移动距离：200+300；上下移动距离120+100
			*/
			//x的倍率 1.66 =左侧大正方形的左右移动距离(3000-1000)除以右侧小正方形的左右移动距离(200+300)
			//y的倍率 2.5 =左侧大正方形的上下移动距离(3000-600)除以右侧小正方形的上下移动距离(120+100)
			nodeMouseMove(e) {
				if(this.mouseState){
					
					let x = e.clientX - this.canvasOffsetX
					let y = e.clientY - this.canvasOffsetY
					if(x>=0){
						x = 0
					}
					if(Math.abs(x)>(Math.abs(this.initPx.x)*2-2)){
						console.log(Math.abs(this.initPx.x)*2)
						x = -Math.abs(this.initPx.x)*2
					}
					if(y>=0){
						y = 0
					}
					if(Math.abs(y)>Math.abs(this.initPx.y)*2){
						y = -Math.abs(this.initPx.y)*2
					}
// 					let magnificationX = (3000-this.width)/(200+300);
// 					let magnificationY = (3000-this.height)/(120+100)
					// 左侧大矩形
					this.dynamicPx.x = x;
					this.dynamicPx.y = y;
					// 右侧小矩形
					this.eyesdynamicPx.x = x/this.magnificationX+100;
					this.eyesdynamicPx.y = y/this.magnificationY+100;
					console.log(x+','+y)
					console.log(this.eyesdynamicPx.x+','+this.eyesdynamicPx.y)

				}
			},
			nodeMouseUp(e) {
				this.mouseState = false
			},
			// 鹰眼图
			eyesMouseDown(e) {
				this.eyesState = true;
				this.eyescanvasOffsetX=e.clientX-e.target.offsetLeft;
				this.eyescanvasOffsetY=e.clientY-e.target.offsetTop;
			},
			eyesMouseMove(e) {
				if(this.eyesState){
					let x = e.clientX - this.eyescanvasOffsetX
					let y = e.clientY - this.eyescanvasOffsetY
					if(x>=99){
						x = 100
					}
					if(Math.abs(x)>=200){
						x = -200
					}
					if(y>=100){
						y = 100
					}
					if(Math.abs(y)>100){
						y = -100
					}
					console.log(x+','+y)
					// 右侧小矩形
					this.eyesdynamicPx.x = x;
					this.eyesdynamicPx.y = y;
					// 左侧大矩形
					this.dynamicPx.x = (x-100)*this.magnificationX;
					this.dynamicPx.y = (y-100)*this.magnificationY;
					
			
				}
			},
			eyesMouseUp(e) {
				this.eyesState = false
			},
			
			//删除节点，
			nodeRemove(id) {
				let that = this;
				//删除接点的时候要删除连接点
				this.jspNode.remove(this.nodeId + id)
				this.eyesData = that.getEyesData();
				//删除store里面的node
				var ndata = Object.assign([], that.nodeData);
				for (var j = 0; j < ndata.length; j++) {
					if (id == ndata[j].id) {
						ndata.splice(j, 1)
					}
				}
			},
			// 封装数据
			save() {
				var container = this.jspNode.getSelector('.j-node');
				let postData = [],
					relation = []
				let nodeIdlength = this.nodeId.length
				for (let c of container) {
					let id = c.id.substr(nodeIdlength)
					for (let n of this.nodeData) {
						if (id == n.id) {
							postData.push(n)
						}
					}
				}
				var connects = this.jspNode.getConnections()
				for (let con of connects) {
					let o = {
						source: con.sourceId.substr(nodeIdlength),
						target: con.targetId.substr(nodeIdlength)
					}
					relation.push(o)
				}
				let ndata = {
					postData: postData,
					connect: relation
				}
				this.$emit("getNodeData", ndata);
			},
			getEyesData(position){
				var container = this.jspNode.getSelector('.j-node');
				let postData = []
				let nodeIdlength = this.nodeId.length
				let nData =Object.assign([], this.nodeData)
				for (let c of container) {
					let id = c.id.substr(nodeIdlength)
					for (let n of nData) {
						if (id == n.id) {
							
							postData.push(n)
						}
					}
				}
// 				for (let p of postData) {
// 					p.x = (p.x- Math.abs(position.x))/(this.width/100);
// 					p.y = (p.y- Math.abs(position.y))/(this.height/100) 
// 				}
				return postData;
			},
			// 样式修改
			lineSet(type) {
				let strlinetype = "Flowchart"
				switch (type) {
					case 'Bezier':
						strlinetype = 'Bezier'
						break;
					case 'Flowchart':
						strlinetype = 'Flowchart'
						break;
					case 'Straight':
						strlinetype = 'Straight'
						break;
					default:
						break;
				}
				// 修改完样式之后，我们要把页面上已经存在的节点的样式修改成当前选中的连接样式
				this.changeBaseConfig(0, strlinetype)
			},
			// 样式修改
			arrowSet(type) {
				let arrowType = null;
				switch (type) {
					case 1:
						arrowType = ["Arrow", {
							width: 10,
							length: 10,
							location: 1,
							paintStyle: {
								lineWidth: 5,
								stroke: '#909399',
								fill: '#909399',
							}
						}]
						break;
					case 0:
						arrowType = ["Arrow", {
							width: 10,
							length: 10,
							location: 1,
							paintStyle: {
								lineWidth: 5,
								stroke: 'transparent',
								fill: 'transparent',
							}
						}]
						break;
					default:
						break;
				}
				// 修改完样式之后，我们要把页面上已经存在的节点的样式修改成当前选中的连接样式
				this.changeBaseConfig(1, arrowType)
			},
			changeBaseConfig(sign, strlinetype) {
				//sign 1 是否显示箭头   0 显示线段的类型
				let arrnode = this.jspNode.getSelector('.j-node');
				for (let i = 0; i < arrnode.length; i++) {
					let arrendpoints = this.jspNode.getEndpoints(arrnode[i].id);
					if (arrendpoints == undefined || arrendpoints == null) {
						return;
					}
					let oconnector = arrendpoints[0].connector; //线段的类型
					if (oconnector == null || oconnector == undefined) {
						return;
					}
					let connectorOverlays = arrendpoints[0].connectorOverlays; //箭头的样式
					if (connectorOverlays == null || connectorOverlays == undefined) {
						return;
					}
					if (sign == 1) {
						arrendpoints[0].connectorOverlays[0] = strlinetype
					} else if (sign == 0) {
						oconnector[0] = strlinetype;
					}
				}
			},
		}
	}
</script>

<style lang="scss">
	@import "../../assets/iconfont.css";

	* {
		padding: 0;
		margin: 0;
		box-sizing: border-box;
		font-size: 14px;
	}
	.content {
		width: 100%;
		height: 100%;
	}

	.j-container {
		position: relative;
		overflow: hidden;
	}
	#nodeCanvas {
		position: absolute;
		width: 800px;
		height: 800px;
	}
	// 鹰眼图
	.little-map{
		width: 100px;
		height: 100px;
		position: absolute;
		top:20px;
		right: 20px;
		box-shadow: #606266 0px 0px 3px;
		z-index: 100;
		overflow: hidden;
	}
	.littie-div{
		position: absolute;
		width: 10px;
		height: 10px;
		background: #0077AA;
	}
	.mask{
		position: absolute;
		top: 0px;
		left: 0px;
		width: 100px;
		height: 100px;
		background: rgba(0,0,0,0.2);
	}
	.j-middle-con{
		width: 100%;
		height: 100%;
	}
	// 节点样式
	.j-node {
		position: absolute;
		text-align: center;
		width: 70px;
		height: 70px;
		line-height: 70px;
		color: #595959;
		border-radius: 5px;
		cursor: move;
	}
	.del {
		line-height: 20px;
		width: 20px;
		height: 20px;
		position: absolute;
		top: -10px;
		right: -18px;
		background: rgba(0,0,0,0.2);
		border-radius: 50%;
		cursor: pointer;
		color: #fff;
	}

	// 头部工具
	.j-header {
		line-height: 42px;
		height: 42px;
		border: 1px solid #E9E9E9;
		box-shadow: 0px 8px 12px 0px rgba(0, 52, 107, 0.04);

	}

	.j-header span {
		width: 27px;
		height: 27px;
		margin: 7px 5px;
		padding: 5px;
		cursor: pointer;
	}

	.j-header span:hover {
		box-shadow: #606266 0px 0px 3px;
	}

	.j-header .disable {
		color: rgba(0, 0, 0, 0.25);
	}

	// 左侧样式
	.j-panel {
		padding: 8px 15px;
		float: left;
		background: #F7F9FB;
		width: 200px;
		height: 100vh;
		padding-top: 8px;
		border-right: 1px solid #E6E9ED;
	}

	.flex {
		display: flex;
		justify-content: space-between;
		flex-wrap: wrap;
	}

	.flex-child {
		width: 80px;
		height: 80px;
		padding: 5px;
	}

	.flex-child:hover {
		box-shadow: #606266 0px 0px 3px;
	}

	.flex-child span {
		display: inline-block;
		width: 70px;
		height: 70px;
		text-align: center;
		line-height: 70px;
		font-size: 14px;
		border-radius: 5px;
		cursor: move;
	}

	.type1 {
		border: 2px solid rgba(114, 46, 209, 0.5);
		background: rgba(114, 46, 209, 0.1);
	}

	.active-type1 {
		border: 2px solid rgba(114, 46, 209, 0.9);
		background: rgba(114, 46, 209, 0.6);
	}

	.type2 {
		border: 2px solid rgba(24, 144, 255, 0.5);
		background: rgba(24, 144, 255, 0.1);
	}

	.active-type2 {
		border: 2px solid rgba(24, 144, 255, 0.9);
		background: rgba(24, 144, 255, 0.6);
	}

	.type3 {
		border: 2px solid rgba(75, 205, 206, 0.5);
		background: rgba(75, 205, 206, 0.1);
	}

	.active-type3 {
		border: 2px solid rgba(75, 205, 206, 0.9);
		background: rgba(75, 205, 206, 0.6);
	}

	.type4 {
		border: 2px solid rgba(250, 140, 22, 0.5);
		background: rgba(250, 140, 22, 0.1);
	}

	.active-type4 {
		border: 2px solid rgba(250, 140, 22, 0.9);
		background: rgba(250, 140, 22, 0.6);
	}
// 右侧数据
	.d-title {
		height: 32px;
		border-top: 1px solid #DCE3E8;
		border-bottom: 1px solid #DCE3E8;
		background: #EBEEF2;
		color: #000;
		line-height: 28px;
		padding-left: 12px;
	}

	

	.j-data {
		position: absolute;
		right: 0;
		top: 42px;
		width: 220px;
		height: 100px;
		border-left: 1px solid #E6E9ED;
	}

	.d-form {
		padding: 16px 8px;
	}

	.d-p {
		margin-bottom: 12px;
	}

	.d-p input {
		width: 120px;
		margin-left: 16px;
		border: 1px solid #d9d9d9;
		line-height: 30px;
		border-radius: 5px;
	}

	.d-p input:hover {
		border: 1px solid #409eff;

	}
</style>
